package com.bba.cloud.search.handler;

import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.HighlightParameters;
import org.springframework.data.elasticsearch.core.SearchHits;

import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;

public class HighlightQueryHandler<T>{
    /**
     * @Highlight 是代表当前查询方法需要高亮返回，
     * 通过指定里边的fields (传入注解@HighlightField)来指定要高亮的字段，
     * 如果不指定 parameters 属性，则默认使用 em 标签包裹匹配的关键字。
     * 配合parameters属性(传入注解@HighlightParameters)可以指定高亮方式，
     * preTags 指定匹配关键字之前的标签，postTags 指定匹配关键字之后的标签；
     * 设置numberOfFragments可以指定返回的片段数，默认是返回全部片段，设置为3返回3个片段，设置为0返回一个片段，包含全部内容，
     * 也就是 SearchHit中的highlightFields全部显示。
     * fragmentSize片段长度
     */
    @Highlight(
            fields = {@HighlightField(name = "sku_name")},
            parameters =  @HighlightParameters(
                    preTags = "<strong style='color:red'>",
                    postTags = "</strong>",
                    fragmentSize = 100
            )
    )
    public void skuName(){}

    /**
     * 高亮替换，将高亮字段替换成HTML标记字段
     * @param searchHits
     * @param clazz
     * @param fieldName
     * @return
     * @param <T>
     */
    public static<T> List<T> parseHighlightResult(SearchHits<T> searchHits, Class<T> clazz, String fieldName){
        try {
            Field field = clazz.getDeclaredField(fieldName);
            List<T> list = searchHits.getSearchHits().stream().map(e -> {
                T obj = e.getContent();
                // 获取高高亮结果字段
                if (e.getHighlightFields() != null && e.getHighlightFields().size() > 0) {
                    String text = e.getHighlightFields().get(fieldName).get(0);
                    // 替换字段
                    field.setAccessible(true);
                    try {
                        field.set(obj, text);
                    } catch (IllegalAccessException ex) {
                        throw new RuntimeException(ex);
                    }
                }
                return obj;
            }).collect(Collectors.toList());
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
